package com.project_doctor.controller;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.project_doctor.code.SystemCode;
import com.project_doctor.pojo.Contract;
import com.project_doctor.pojo.Resident;
import com.project_doctor.pojo.common.MyPageData;
import com.project_doctor.pojo.dto.*;
import com.project_doctor.pojo.vo.ContractDetailVO;
import com.project_doctor.pojo.vo.ContractVO;
import com.project_doctor.pojo.vo.DetailsVO;
import com.project_doctor.service.ContractService;
import com.project_doctor.service.ResidentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.List;

/**
 * 签约管理控制器
 */
@RestController
@RequestMapping("/contract")
@Slf4j
public class ContractController {

    @Autowired
    private ContractService contractService;

    @Autowired
    private ResidentService residentService;

    /**
     * 根据居民ID获取签约信息
     * @param residentId 居民ID
     * @return 签约信息列表
     */
    @GetMapping("/getContractInfo/{residentId}")
    public ResponseEntity<List<ContractInfoDTO>> getContractsByResidentId(@PathVariable Integer residentId) {
        try {
            List<ContractInfoDTO> contracts = contractService.getContractInfoByResidentId(residentId);
            return ResponseEntity.ok(contracts);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.internalServerError().build();
        }
    }

    @PostMapping("/getAllContract/{pageNum}/{pageSize}")
    public ResponseEntity<?>getAllContract(@PathVariable Integer pageNum,
                                           @PathVariable Integer pageSize,
                                           @RequestBody ContractQueryDTO queryDTO){
        Page<ContractVO> page = contractService.getAllContract(pageNum, pageSize, queryDTO);
        List<ContractVO> contractVOS = page.getRecords();

        MyPageData myPageData = new MyPageData(page.getTotal(),contractVOS);
        return ResponseEntity.ok(myPageData);
    }

    /**
     * 获取指定契约的详细信息
     *
     * 业务逻辑：
     * 1. 根据契约ID查询契约基本信息
     * 2. 关联查询居民信息、医生信息、服务包信息
     * 3. 查询契约的历史状态变更记录
     * 4. 组装完整的契约详情数据返回前端
     *
     * 前端使用场景：点击契约列表中的"查看详情"按钮
     *
     * @param id 契约ID
     * @return 契约详情信息（包含居民、医生、服务包、状态历史等完整信息）
     */
    @GetMapping("/getAllContractDetail/{id}")
    public ResponseEntity<?>getAllContractDetail(@PathVariable Integer id){
        List<ContractDetailVO> voList = contractService.getAllContractDetail(id);
        return ResponseEntity.ok(voList);
    }

    /**
     * 新增契约申请
     *
     * 业务逻辑：
     * 1. 接收前端提交的契约申请数据
     * 2. 验证居民是否已有有效契约（避免重复签约）
     * 3. 验证医生团队服务能力是否已满
     * 4. 创建新的契约记录，初始状态为"待审核"
     * 5. 记录申请时间和申请人信息
     *
     * 前端调用场景：居民填写契约申请表单并提交
     *
     * @param contractDTO 契约申请数据（包含居民ID、医生团队ID、服务包ID、申请原因等）
     * @return 操作结果
     */
    @PostMapping("/addContract")
    public ResponseEntity<?> addContract(@RequestBody ContractDTO contractDTO){
        contractService.saveContract(contractDTO);
        return ResponseEntity.ok("ok");
    }

    /**
     * 审核通过契约申请
     *
     * 业务逻辑：
     * 1. 验证审核人权限（只有管理员可以审核）
     * 2. 检查契约当前状态（只有"待审核"状态才能通过）
     * 3. 更新契约状态为"已生效"
     * 4. 记录审核人、审核时间、审核意见
     * 5. 生成契约正式编号
     * 6. 发送通知给居民（短信/邮件）
     *
     * @param approveDTO 审核通过数据（包含契约ID、审核意见、审核人等）
     * @return 操作结果
     */
    @PostMapping("/approve")
    public ResponseEntity<?> approve(@RequestBody ContractApproveDTO approveDTO){
        log.info("审核通过契约申请: {}", approveDTO);
        contractService.approveContract(approveDTO);
        return ResponseEntity.ok("ok");
    }

    /**
     * 驳回契约申请
     *
     * 业务逻辑：
     * 1. 验证审核人权限
     * 2. 检查契约当前状态（只有"待审核"状态才能驳回）
     * 3. 更新契约状态为"已驳回"
     * 4. 记录驳回原因、驳回人、驳回时间
     * 5. 发送驳回通知给申请人
     * 6. 可选：提供重新申请的建议
     *
     * @param rejectDTO 驳回数据（包含契约ID、驳回原因、审核人等）
     * @return 操作结果
     */
    @PostMapping("/reject")
    public ResponseEntity<?> reject(@RequestBody ContractRejectDTO rejectDTO){
        log.info("驳回契约申请: {}", rejectDTO);
        contractService.rejectContract(rejectDTO);
        return ResponseEntity.ok("ok");
    }


    /**
     * 导出Excel表格
     * 签约数据
     *
     */
    @GetMapping("/exportExcel")
    public void download(HttpServletResponse response) throws IOException {
        // 这里注意 有同学反应使用swagger 会导致各种问题，请直接用浏览器或者用postman
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("房屋信息", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

        ContractQueryDTO queryDTO = new ContractQueryDTO();
        Page<ContractVO> contract = contractService.getAllContract(1,  1000,queryDTO);

        List<ContractVO> contractVOList = contract.getRecords();

        EasyExcel.write(response.getOutputStream(), ContractVO.class).sheet("模板").doWrite(contractVOList);
    }

    //待处理页面分页
    @PostMapping("/pendingList/{pageNum}/{pageSize}")
    public ResponseEntity<?> getContractVoList(@RequestBody ContractQueryDTO queryDTO,
                                               @PathVariable Integer pageNum,
                                               @PathVariable Integer pageSize) {
        // 设置需要排除的状态值
        queryDTO.setExcludeStatusList(Arrays.asList(1, 2, 4, 9, 10));
        Page<ContractVO> page = contractService.getContractVoList(queryDTO,pageNum,pageSize);
        List<ContractVO> contractVOS = page.getRecords();

        MyPageData data = new MyPageData(page.getTotal(),contractVOS);

        return ResponseEntity.ok(data);
    }
    //服务记录页面分页
    @PostMapping("/recordList/{pageNum}/{pageSize}")
    public ResponseEntity<?> getList(@RequestBody ContractQueryDTO queryDTO,
                                     @PathVariable Integer pageNum,
                                     @PathVariable Integer pageSize) {
        // 设置需要排除的状态值
        queryDTO.setExcludeStatusList(Arrays.asList(9, 10));
        Page<ContractVO> page = contractService.getContractVoList(queryDTO,pageNum,pageSize);
        List<ContractVO> contractVOS = page.getRecords();

        MyPageData data = new MyPageData(page.getTotal(),contractVOS);

        return ResponseEntity.ok(data);
    }
    //获取服务详情页
    @GetMapping("/selectContractDetail/{contractId}")
    public ResponseEntity<?> selectContractDetail(@PathVariable Integer contractId) {
        DetailsVO detailsVO = contractService.selectContractDetail(contractId);
        return ResponseEntity.ok(detailsVO);
    }

    //修改服务详情
    @PutMapping("/updateService")
    @Transactional
    public ResponseEntity<?> updateService(@RequestBody DetailsDTO dto) {
        residentService.updateService(dto);
        contractService.updateService(dto);
        return ResponseEntity.ok(SystemCode.UPDATE_SUCCESS.getMessage());
    }
    //新增服务详情
    @PostMapping("/addService")
    public ResponseEntity<?> addService(@RequestBody DetailsDTO dto) {
        contractService.addService(dto);
        return ResponseEntity.ok(SystemCode.ADD_SUCCESS.getMessage());
    }
    //服务详情页审核通过按钮
    @PutMapping("/updateApproved/{contractId}/{userName}")
    public ResponseEntity<?> updateApproved(@PathVariable Integer contractId,@PathVariable String  userName ) {
        contractService.updateApproved(contractId,userName);
        return ResponseEntity.ok(SystemCode.APPROVED_SUCCESS.getMessage());
    }
    //服务详情页服务取消按钮
    @PutMapping("/updateCancel")
    public ResponseEntity<?> updateCancel(@RequestBody CancelDTO dto) {
        contractService.updateCancel(dto);
        return ResponseEntity.ok(SystemCode.CANCEL_SUCCESS.getMessage());
    }
    //服务详情页服务驳回按钮
    @PutMapping("/updateReject")
    public ResponseEntity<?> updateReject(@RequestBody RejectDTO dto) {
        contractService.updateReject(dto);
        return ResponseEntity.ok(SystemCode.REJECT_SUCCESS.getMessage());
    }
    //待处理页面导出Excel
    @GetMapping("/downloadPending")
    public void downloadPending(HttpServletResponse response) throws IOException {
        //查询出 要写入 Excel文件的数据  （手动写）
        ContractQueryDTO queryDTO = new ContractQueryDTO();
        queryDTO.setExcludeStatusList(Arrays.asList(9, 10));
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("待处理服务数据", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

        download(response,queryDTO);
    }
    //服务记录页面导出Excel
    @GetMapping("/downloadRecord")
    public void downloadRecord(HttpServletResponse response) throws IOException {
        //查询出 要写入 Excel文件的数据  （手动写）
        ContractQueryDTO queryDTO = new ContractQueryDTO();
        queryDTO.setExcludeStatusList(Arrays.asList(1, 2, 4, 9, 10));
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("服务记录数据", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

        download(response,queryDTO);
    }
    //导出Excel
    public void download(HttpServletResponse response,ContractQueryDTO queryDTO) throws IOException {
        // 这里注意 有同学反应使用swagger 会导致各种问题，请直接用浏览器或者用postman
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");

        // 3. 关键点：传入一个极大值作为pageSize，模拟“查询全部”
        int MAX_PAGE_SIZE = Integer.MAX_VALUE; // 或实际业务允许的最大值（如 100000）
        Page<ContractVO> page = contractService.getContractVoList(queryDTO, 1, MAX_PAGE_SIZE);
        // 使用 getRecords() 获取真正的数据集合
        List<ContractVO> records = page.getRecords();
        // 注意将上面的 getHouseByPage方法中参数 DTO 加入 required=false

        EasyExcel.write(response.getOutputStream(), ContractVO.class).sheet("模板").doWrite(records);
    }

}
